home *** CD-ROM | disk | FTP | other *** search
/ Megahits 3 / Megahits 3 (1994)(GTI - Rhein-Main-Soft)(DE)[!].iso / module / utilities / archives / mod2midi3.lha / Mod2Midi / source / mod2midi.C < prev    next >
C/C++ Source or Header  |  1992-09-02  |  41KB  |  1,684 lines

  1. /*
  2.  * MIDIMOD.C - Amiga Module to MIDI file converter
  3.  * (c)opyright Andrew Scott 1993
  4.  *
  5.  * Turbo C 2.0
  6.  *
  7.  * Description: Takes a .mod file and has a good go at converting it to
  8.  *              a .mid file. Equivalents to certain .mod samples can be
  9.  *              set to default to particular MIDI instruments. Multiple
  10.  *              MIDI instrument tables should be supported. Note that .mod
  11.  *              and .mid extensions are at the end of the filename.
  12.  *
  13.  * Author: Andrew Scott (Adrenalin Software)
  14.  *
  15.  * Date: 14/3/1993 ver 0.1
  16.  *       20/4/1993 ver 0.2
  17.  *
  18.  **********************************************************************
  19.  *
  20.  * SAS/C 6.51
  21.  *
  22.  * UpDated: 23/Jan/1994 Raul Sobon (Amiga Version  ooooooooooh Yeah!)
  23.  *            15/Feb/1994 Fixed up bugs in midi generation etc..
  24.  *                        ReqTools implemented
  25.  *
  26.  *
  27.  *
  28.  *
  29.  *
  30.  *
  31.  *
  32.  *
  33.  *
  34.  *
  35.  *
  36.  */
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40. #include <ctype.h>
  41. #include <math.h>   /* don't forget to link in appropriate libraries */
  42.  
  43. #include "textwin.h" /* Simple text-windowing environment */
  44. #include "midimod.h" /* Dialog/Info box messages and definitions */
  45.  
  46. bfile    MidFile, ModFile;
  47. char    SongName[128];
  48. samps    Samples;
  49. unsigned long PosLog[128];
  50. int        DrumChann = 9, TempoType = 1, PosI = 0;
  51. string    MidFN, ModFN;
  52. int        numoftracks=0;
  53.  
  54.  
  55. unsigned char Def_Map_filename[]={ DEF_MAPFILE };
  56.  
  57. void OutByte(bfile f, char b)
  58. /* Post: The byte b has been written to the buffer of the file f */
  59. {
  60.     if (f->o == BUFFSIZE) {
  61.         fwrite(f->b, 1, BUFFSIZE, f->f);
  62.         f->o = 0;
  63.       }
  64.     f->b[f->o++] = b;
  65. }
  66.  
  67. void FlushOut(bfile f)
  68. /* Pre: f was opened for writing */
  69. /* Post: The file f has has its buffer flushed */
  70. {
  71.     if (f->o > 0)
  72.         fwrite(f->b, 1, f->o, f->f);
  73.     f->o = 0;
  74. }
  75.  
  76. void CloseOut(bfile f)
  77. /* Pre: f was opened for writing */
  78. /* Post: The file f has been flushed and is now closed */
  79. {
  80.     FlushOut(f);
  81.     fclose(f->f);
  82.     f->f = NULL;
  83. }
  84.  
  85. int OpenOut(bfile f, string fn)
  86. /* Returns: NZ if the file f has been opened for writing with the name fn */
  87. {
  88.     if (f->f != NULL)
  89.         CloseOut(f);
  90.     f->f = fopen(fn, "wb");
  91.     f->o = 0;
  92.     return f->f != NULL;
  93. }
  94.  
  95. unsigned long Beatle(bfile f)
  96. /* Returns: bfile-tell (btell=beatle). The offset from the start */
  97. {
  98.     return ftell(f->f) + f->o;
  99. }
  100.  
  101. unsigned char InByte(bfile f)
  102. /* Pre: f was opened for reading */
  103. /* Returns: The next byte from the file f */
  104. {
  105.     if (f->o == BUFFSIZE && !feof(f->f)) {
  106.         f->r = fread(f->b, 1, BUFFSIZE, f->f);
  107.         if (f->r < BUFFSIZE)
  108.             f->b[f->r] = 0;
  109.         f->o = 0;
  110.     }
  111.     if (f->o < f->r)
  112.          return f->b[f->o++];
  113.     return f->b[f->o];
  114. }
  115.  
  116. void CloseIn(bfile f)
  117. /* Post: The file f is now closed */
  118. {
  119.     fclose(f->f);
  120.     f->f = NULL;
  121. }
  122.  
  123. int OpenIn(bfile f, string fn)
  124. /* Returns: NZ if the file f has been opened for reading with the name fn */
  125. {
  126.     if( f->f )
  127.         CloseIn(f);
  128.     f->f = fopen(fn, "rb");
  129.     f->o = f->r = BUFFSIZE;
  130.     return f->f != NULL;
  131. }
  132.  
  133. void Inskipp(bfile f, unsigned long n) /* Stainless-steel rat for Pres */
  134. /* Pre: f was opened for reading */
  135. /* Post: f's file pointer has skipped forward n bytes */
  136. {
  137.     n += f->o;
  138.     while (n >= BUFFSIZE && !feof(f->f)) {
  139.         f->r = fread(f->b, 1, BUFFSIZE, f->f);
  140.         if (f->r < BUFFSIZE)
  141.             f->b[f->r] = 0;
  142.         n -= BUFFSIZE;
  143.     }
  144.     f->o = n; /* hmmm.. may cause an error if was eof.. X-fingers */
  145. }
  146.  
  147. struct bpos FPos(bfile f)
  148. /* Returns: All necessary information regarding file f's status */
  149. {
  150.     struct bpos x;
  151.  
  152.     x.d = *f;
  153.     x.p = ftell(f->f);
  154.     return x;
  155. }
  156.  
  157. void FGoto(bfile f, struct bpos x)
  158. /* Pre: x was the status of f previously */
  159. /* Post: File f has had its status changed to x */
  160. {
  161.     fseek(f->f, x.p, SEEK_SET);
  162.     *f = x.d;
  163. }
  164.  
  165. int WriteVLQ(bfile f, unsigned long i)
  166. /*
  167.  * Returns: # of bytes written after a variable-length-quantity equivalent
  168.  *    of i has been written to the file f.
  169.  */
  170. {
  171.     int x = 0;
  172.     unsigned long buffer;
  173.  
  174.     buffer = i & 127;
  175.     while ((i >>= 7) > 0)
  176.         buffer = ((buffer << 8) | 128) + (i & 127);
  177.     while (1) {
  178.         OutByte(f, buffer & 255);
  179.         x++;
  180.         if (buffer & 128)
  181.             buffer >>= 8;
  182.         else
  183.             return x;
  184.     }
  185. }
  186.  
  187. string InitFile(bfile f, string deffn, string t, int inpm)
  188. /* Returns: NULL if file is unacceptable, the filename otherwise. The
  189.  *    filename corresponds to file f, type t, with default filename deffn.
  190.  *    Will open an input file if inpm is NZ. deffn will be freed.
  191.  */
  192. {
  193.     int r = 0;
  194.     string newfn;
  195.  
  196.     _IF[1] = t;
  197.     if (deffn==NULL)
  198.         *(deffn = (string) malloc(1)) = 0;
  199.  
  200.     sprintf(  _IF[0],"Select %s", t );
  201.     newfn = FileSelect( _IF , deffn );
  202.     if( deffn )
  203.         free(deffn);
  204.  
  205.     if( newfn ) {                //======== RAUL FIX ==|
  206.         if (! *newfn) {            // PREVIOUS ENFORCER ERROR HERE
  207.             free(newfn);
  208.             return NULL;
  209.         }
  210.         if (inpm)
  211.             r = OpenIn(f, newfn);
  212.         else
  213.         if (fclose(fopen(newfn, "r"))==EOF || InfoBoxOld(_OUTE)=='y')
  214.             r = OpenOut(f, newfn);
  215.         if (!r) {
  216.             free(newfn);
  217.             return NULL;
  218.         }
  219.     }
  220.     return newfn;
  221. }
  222.  
  223. int MKTest(bfile f)
  224. /* Returns: The number of samples in the Module file f */
  225. {
  226.     unsigned long offset;
  227.     int i = 15;
  228.     char s[4];
  229.  
  230.     offset = ftell(f->f);
  231.     if (!fseek(f->f, 1080, SEEK_SET)) {
  232.         fread(s, 1, 4, f->f);
  233.         if (!memcmp(s,"M.K.",4) || !memcmp(s,"M!K!",4) || !memcmp(s,"FLT4",4))
  234.             i = 31;
  235.         else if (!memcmp(s,"FLT8",4))
  236.             i = 0;
  237.     }
  238.     fseek(f->f, offset, SEEK_SET);
  239.     return i;
  240. }
  241.  
  242. string SimplifyName(string s)
  243. /*
  244.  * Returns: A string similar to s, but has had any nasty headers removed
  245.  *    any leading spaces or trailing spaces, and all made lower-case with
  246.  *    any intermediate spaces replaced by underbar-characters
  247.  */
  248. {
  249.     string t, r, x;
  250.  
  251.     x = strchr(s, ':');
  252.     if (x != NULL && x-s == 5 && tolower(s[0])=='s' && tolower(s[1])=='t' &&
  253.      s[2]=='-') {
  254.         r = x = (string) malloc(18);
  255.         t = s + 6;
  256.         while (*(x++) = *(t++)); /* remove soundtracker header */
  257.     } else
  258.         strcpy(r = (string) malloc(1+strlen(s)), s); /* strdup? */
  259.     for (t = r; *t == ' '; t++);
  260.     x = r;
  261.     while (*(x++) = *(t++)); /* remove leading spaces */
  262.     if (*r) {
  263.         x--;
  264.         while (*(--x) == ' ') /* remove trailing spaces */
  265.             *x = 0;
  266.     }
  267.     for (x = r; *x; x++) /* fill intermediate spaces with _ */
  268.         if (*x == ' ')
  269.             *x = '_';
  270.     if( r ){
  271.         t = r = (string) realloc(r, strlen(r) + 1);
  272.     }
  273.     for (; *t; t++)
  274.         *t = tolower(*t); /* make the lot lower-case */
  275.     return r;
  276. }
  277.  
  278. string GetLine(FILE *f)
  279. /* Returns: Next line from file f, NULL on error/eof */
  280. {
  281.     string s, t;
  282.     int c;
  283.  
  284.     if ((t = s = (string) malloc(MAXSTRING))==NULL) {
  285.         InfoBox(_OOME);
  286.         return NULL;
  287.     }
  288.     while ((c = fgetc(f)) != EOF && c != '\n')
  289.         *(t++) = c;
  290.     if (s == t) {
  291.         free(s);
  292.         return NULL;
  293.     }
  294.     *t = 0;
  295.     return (string) realloc(s, t-s+1);
  296. }
  297.  
  298. int ReadModSpecs(bfile f, string n, samps s)
  299. /*
  300.  * Returns: Z if f is not a supported Amiga Module, else n is set to
  301.  * be the name of the Module and s is set to hold sample information
  302.  */
  303. {
  304.     unsigned char b, c;
  305.     int i, okmodule;
  306.     string t1;
  307.     samp *t2;
  308.  
  309.     for (i = 20, t1 = n; i--; *(t1++) = InByte(f));
  310.     okmodule = !*n || isprint(*n);
  311.     *t1 = 0;
  312.     c = s->n = MKTest(f);
  313.     okmodule = okmodule && c;
  314.     for (t2 = s->s; c--; t2++) {
  315.         for (i = 22, t1 = t2->n; i--; *(t1++) = InByte(f));
  316.         okmodule = okmodule && (!*(t2->n) || isprint(*(t2->n)));
  317.         *t1 = 0;
  318.         b = InByte(f);
  319.         t2->l = 256 * b + InByte(f);
  320.         if (t2->l < 4)
  321.             t2->l = 0;    /* if the sample is this small, not worth processing */
  322.         b = InByte(f);
  323.         t2->v = InByte(f);
  324.         InByte(f);
  325.         InByte(f);
  326.         b = InByte(f);
  327.         if (256 * b + InByte(f) > 1 && t2->l)
  328.             t2->l = -1;    /* looping: plays 'forever' */
  329.         t2->m = 0;
  330.     }
  331.  
  332.     return !feof(f->f) && okmodule;
  333. }
  334.  
  335. void ScanSamples(samps s)
  336. /*
  337.  * Post: Sample data for ModFile has been scanned and samples in s have
  338.  * been given "reasonable" values for volume shifting and transpositions
  339.  * I hope :)
  340.  */
  341. {
  342.     samp *sam;
  343.     unsigned int maxpat = 0, i, j, k;
  344.     unsigned char x;
  345.     signed char c[SCANSIZE];      /* look at first SCANSIZE bytes of sample */
  346.     signed char max, min, *p;
  347.     unsigned long offset, len, lenarry[31];
  348.     long sum;
  349.     double ratio, junk;
  350.  
  351.     offset = ftell(ModFile->f);
  352.     fseek(ModFile->f, 42, SEEK_SET);
  353.     for (i = 0; i < s->n; i++) {    /* need to get actual lengths */
  354.         fread(&x, 1, 1, ModFile->f);
  355.         lenarry[i] = 256 * x;
  356.         fread(&x, 1, 1, ModFile->f);
  357.         lenarry[i] += x;
  358.         lenarry[i] *= 2;
  359.         fseek(ModFile->f, 28, SEEK_CUR);
  360.     }
  361.     fseek(ModFile->f, 20 + 30 * s->n, SEEK_SET);
  362.     fread(&x, 1, 1, ModFile->f);
  363.     fread(c, 1, 129, ModFile->f);
  364.     for (; x; x--)
  365.         if (c[x] > maxpat)
  366.             maxpat = c[x];
  367.     len = 1024L * (maxpat + 1) + 30 * s->n + ((s->n > 30) ? 4 : 0) + 150;
  368.     fseek(ModFile->f, len, SEEK_SET);
  369.     for (i = 0, sam = s->s; i < s->n; i++, sam++) {
  370.         sam->t[0] = 0; /* set transposition values to 0 */
  371.         sam->t[1] = 0;
  372.         sam->t[2] = 0;
  373.         sam->a[0] = 0;
  374.         if (!sam->l) {
  375.             sam->a[1] = 1; /* no sample = no volume shifting */
  376.             sam->a[2] = 1;
  377.             fseek(ModFile->f, lenarry[i], SEEK_CUR);
  378.         } else {
  379.             len = min(lenarry[i], SCANSIZE);
  380.             if (!(j = len = fread(c, 1, len, ModFile->f)))
  381.                 len = 1;
  382.             fseek(ModFile->f, lenarry[i] - j, SEEK_CUR);
  383.             min = 127;
  384.             max = -128;
  385.             sum = 0;
  386.             for (p = c; j--; p++) {
  387.                 sum += *p;
  388.                 if (*p > max)
  389.                     max = *p;
  390.                 if (*p < min)
  391.                     min = *p;
  392.             }
  393.             ratio = 1.0 * sum / len;  /* get average .. normally ~0 */
  394.             if (fabs(max - ratio) > fabs(min - ratio))
  395.                 ratio = fabs(min - ratio) / 64.0;
  396.             else
  397.                 ratio = fabs(max - ratio) / 64.0;
  398.             j = k = 1;
  399.             while (k++ < 15)    /* now find decent rational approx. */
  400.                 if (fabs(modf(ratio * k, &junk)-.5) > fabs(modf(ratio * j, &junk)-.5))
  401.                     j = k;
  402.             if (!(sam->a[1] = ratio * j + 0.5)) {
  403.                 sam->a[1] = 1;   /* if really small scaling needed.. */
  404.                 sam->a[2] = 16;
  405.             } else
  406.                 sam->a[2] = j;
  407.         }
  408.     }
  409.     fseek(ModFile->f, offset, SEEK_SET);
  410. }
  411.  
  412. int SetDefaults(samps s, string fn)
  413. /*
  414.  * Returns: NZ if the samples in s have been sucessfully allocated default
  415.  *    values corresponding to definitions in the DEF_MAPFILE file, and from
  416.  *    a .mm file corresponding to the filename fn
  417.  */
  418. {
  419.     FILE *f;
  420.     char i, m[MAXSTRING+200];
  421.     int d, e[6], v;
  422.     samp *sam;
  423.     string n, t;
  424.     bfile mmf;
  425.  
  426.  
  427. //printf("sd: strlen(fn)=%d\n",strlen(fn));
  428.     t = strchr(strcpy(m, fn), '.');
  429.     if (t==NULL) {
  430.         i = strlen(m);
  431.         m[i] = '.';
  432.     }
  433.     else
  434.         i = t-m;
  435.  
  436.     m[++i] = 'm';
  437.     m[++i] = 'm';
  438.     m[++i] = 0;
  439.     mmf->f = NULL;
  440.     if( OpenIn(mmf, m) ) {
  441.         for (i = s->n, sam = s->s; i--; sam++) {
  442.             sam->m = InByte(mmf);
  443.             sam->t[0] = (signed char) InByte(mmf);
  444.             sam->t[1] = (signed char) InByte(mmf);
  445.             sam->t[2] = (signed char) InByte(mmf);
  446.             sam->a[0] = (signed char) InByte(mmf);
  447.             sam->a[1] = (signed char) InByte(mmf);
  448.             sam->a[2] = (signed char) InByte(mmf);
  449.         }
  450.         CloseIn(mmf);
  451.     }
  452.     else {
  453.         ScanSamples(s);
  454.     }
  455.  
  456.     if( !(f = fopen( Def_Map_filename , "rt")) ) {
  457.         _NOFIL[2] = Def_Map_filename;
  458.         InfoBox(_NOFIL);
  459.         return 0;
  460.     }
  461.     i = s->n;
  462.     for (sam = s->s; i--; sam++) {
  463.         if (sam->l) {
  464.             n = SimplifyName(sam->n);
  465.             t = GetLine(f);
  466.             e[3] = 0;       /* These are the default volume constants */
  467.             e[4] = 1;
  468.             e[5] = 1;
  469.             sscanf(t, "%s %d %d %d %d %d %d %d", m, &d, &e[0], &e[1], &e[2],
  470.                 &e[3], &e[4], &e[5]);
  471.             if ((v = strcmp(m, n))>0) {
  472.                 rewind(f);
  473.                 if(t) free(t);
  474.                 t = GetLine(f);
  475.                 e[3] = 0;
  476.                 e[4] = 1;
  477.                 e[5] = 1;
  478.                 sscanf(t, "%s %d %d %d %d %d %d %d", m, &d, &e[0], &e[1], &e[2],
  479.                     &e[3], &e[4], &e[5]);
  480.                 v = strcmp(m, n);
  481.             }
  482.             if(t) free(t);
  483.             while (v < 0 && (t = GetLine(f)) != NULL) {
  484.                 e[3] = 0;
  485.                 e[4] = 1;
  486.                 e[5] = 1;
  487.                 sscanf(t, "%s %d %d %d %d %d %d %d", m, &d, &e[0], &e[1], &e[2],
  488.                     &e[3], &e[4], &e[5]);
  489.                 if(t) free(t);
  490.                 v = strcmp(m, n);
  491.             }
  492.             if (!v) {
  493.                 sam->m = d;
  494.                 sam->t[0] = e[0];
  495.                 sam->t[1] = e[1];
  496.                 sam->t[2] = e[2];
  497.                 sam->a[0] = e[3];
  498.                 sam->a[1] = e[4];
  499.                 sam->a[2] = e[5];
  500.             }
  501.             if(n) free(n);
  502.         }
  503.     }
  504.     fclose(f);
  505.     return 1;
  506. }
  507.  
  508. void SaveDefaults(samps s, string fn)
  509. /*
  510.  * Post: The samples attributes in s have been written to a .mm file
  511.  *   corresponding to the filename fn
  512.  */
  513. {
  514.     char m[MAXSTRING];
  515.     string t;
  516.     char i;
  517.     bfile mmf;
  518.     samp *sam;
  519.  
  520.     t = strchr(strcpy(m, fn), '.');
  521.     if (t==NULL) {
  522.         i = strlen(m);
  523.         m[i] = '.';
  524.     } else
  525.         i = t-m;
  526.     m[++i] = 'm';
  527.     m[++i] = 'm';
  528.     m[++i] = 0;
  529.     mmf->f = NULL;
  530.     if (!OpenOut(mmf, m))
  531.         return;
  532.     for (i = s->n, sam = s->s; i--; sam++) {
  533.         OutByte(mmf, sam->m);
  534.         OutByte(mmf, sam->t[0]);
  535.         OutByte(mmf, sam->t[1]);
  536.         OutByte(mmf, sam->t[2]);
  537.         OutByte(mmf, sam->a[0]);
  538.         OutByte(mmf, sam->a[1]);
  539.         OutByte(mmf, sam->a[2]);
  540.     }
  541.     CloseOut(mmf);
  542. }
  543.  
  544. void NullArryFree(string *sp)
  545. /* Post: The NULL-terminated array sp is gone */
  546. {
  547.     string *t;
  548.  
  549.     t = sp;
  550.     while (*t != NULL)
  551.         free(*(t++));
  552.     free(sp);
  553. }
  554.  
  555. int Instrument( void )
  556. /* Returns: MIDI instrument selected from file DEF_INSFILE */
  557. {
  558.     static int w = 0, doff = -1;
  559.     static string *sp = NULL;
  560.     int c;
  561.  
  562.     if (sp == NULL) {
  563.         FILE *f;
  564.         string *t, s;
  565.         int x, i = 1;
  566.  
  567.         if ((f = fopen(DEF_INSFILE, "rt"))==NULL) {
  568.             _NOFIL[2] = DEF_INSFILE;
  569.             InfoBox(_NOFIL);
  570.             return -1;
  571.         }
  572.         if ((t = sp = (string *) malloc(257 * sizeof(string)))==NULL) {
  573.             InfoBox(_OOME);
  574.             return -1;
  575.         }
  576.         while ((s = GetLine(f)) != NULL)
  577.             if (x = strlen(s)) { /* ignore blank lines */
  578.                 i++;
  579.                 if (x > w)
  580.                     w = x;
  581.                 *(t++) = s;
  582.                 if (doff < 0 && *s=='D')  /* take note of first drum position */
  583.                     sscanf(s, "D%d ", &doff);
  584.             }
  585.         *t = NULL;
  586.         sp = (string *) realloc(sp, i * sizeof(string)); /* i <= 257 */
  587.         fclose(f);
  588.     }
  589.     c = ScrollChoice("MIDI Instruments", sp, w);
  590.     if (c>127)
  591.         c += doff;
  592.     return c;
  593. }
  594.  
  595. string MIDIVal(samp *sam)
  596. /* Returns: a string representing the MIDI instrument *sam */
  597. {
  598.     string s;
  599.  
  600.     s = (string) malloc(5);
  601.     if (sam->m < 128)
  602.         sprintf(s, "%4d", (int)(sam->m+1) );
  603.     else
  604.         sprintf(s, "D%3d", sam->m - 128);
  605.     return s;
  606. }
  607.  
  608. string TransVal(samp *sam)
  609. /* Returns: a string representing the transpose amount of *sam */
  610. {
  611.     string s;
  612.  
  613.     s = (string) malloc(15);
  614.     if (!sam->t[1])
  615.         sprintf(s, "          %4d", sam->t[0]);
  616.     else if (!sam->t[2])
  617.         sprintf(s, "     %4d,%4d", sam->t[0], sam->t[1]);
  618.     else
  619.         sprintf(s, "%4d,%4d,%4d", sam->t[0], sam->t[1], sam->t[2]);
  620.     return s;
  621. }
  622.  
  623. string VolumeVal(samp *sam)
  624. /* Returns: a string representing the volume shifting formula for *sam */
  625. {
  626.     string s;
  627.  
  628.     s = (string) malloc(17);
  629.     if (sam->a[0] < 0)
  630.         sprintf(s, "(? -%3d)*%3d/%3d", abs(sam->a[0]), sam->a[1], sam->a[2]);
  631.     else
  632.         sprintf(s, "(? +%3d)*%3d/%3d", sam->a[0], sam->a[1], sam->a[2]);
  633.     return s;
  634. }
  635.  
  636. string NullVal(samp *sam)
  637. /* Returns: an empty string */
  638. {
  639.     string s;
  640.  
  641.     *(s = (string) malloc(1)) = 0;
  642.     return s;
  643. }
  644.  
  645. int Sample(samps s, string (*MIDIVal)(samp *x), int w)
  646. /* Returns: Sample selected from list of samples, -1 on error */
  647. {
  648.     string *sp, *t, p;
  649.     samp *sam;
  650.     int i;
  651.  
  652.     if ((t = sp = (string *) malloc((s->n + 1) * sizeof(string)))==NULL) {
  653.         InfoBox(_OOME);
  654.         return -1;
  655.     }
  656.     for (i = s->n, sam = s->s; i--; sam++) {
  657.         *t = (string) malloc(25 + w);
  658.         p = MIDIVal(sam);
  659.         sprintf(*t, "%c%-22s %s", (sam->l) ? '*' : ' ', sam->n, p);
  660.         free(p);
  661.         t++;
  662.     }
  663.     *t = NULL;
  664.     i = ScrollChoice("Select Sample", sp, 24 + w);
  665.     NullArryFree(sp);
  666.     return i;
  667. }
  668.  
  669. int ChooseChannels(samps s)
  670. /*
  671.  * Returns: The number of different channels needed to play instruments. If
  672.  *    that number is not greater than 16, upto 16 channels will be allocated
  673.  *    to the samples.
  674.  */
  675. {
  676.     unsigned char c, d = 0, i[128], m, n, numchan;
  677.     samp *sam1, *sam2;
  678.  
  679.     n = s->n;
  680.     sam1 = s->s;
  681.     memset(i, 0, 128);
  682.     for (n = s->n, sam1 = s->s; n--; sam1++) {
  683.         sam1->c = -1;
  684.         if (sam1->l)
  685.             if (sam1->m > 127) {
  686.                 d = 1;
  687.                 sam1->c = DrumChann;
  688.             } else
  689.                 i[sam1->m] = 1;
  690.         else
  691.             sam1->m = 0;
  692.     }
  693.     for (numchan = d, n = 128; n--; numchan += i[n]);
  694.     if (numchan > 16)
  695.         return numchan;
  696.     /* Ok.. now we must go through and set channels appropriately */
  697.     m = s->n;
  698.     sam1 = s->s;
  699.     c = 0;
  700.     while (m--) {
  701.         if (sam1->c < 0) {
  702.             sam1->c = c;
  703.             n = m;
  704.             sam2 = sam1 + 1;
  705.             while (n--) {
  706.                 if (sam2->c < 0)
  707.                     if (sam2->m == sam1->m || ! sam2->l)
  708.                         sam2->c = c;
  709.                 sam2++;
  710.             }
  711.             if (++c == DrumChann && d)
  712.                 c++;
  713.         }
  714.         sam1++;
  715.     }
  716.     return numchan;
  717. }
  718.  
  719. void MapSamples(samps s)
  720. /* Post: The samples s have been allocated appropriate instruments, we hope */
  721. {
  722.     int i, j;
  723.  
  724.     do
  725.         if ((i = Sample(s, MIDIVal, 4))>=0 && (j = Instrument())>=0)
  726.             s->s[i].m = j;
  727.     while (i>=0);
  728. }
  729.  
  730. void SaveSamp(samp sam)
  731. /* Post: The sample sam has been updated in the DEF_MAPFILE file */
  732. {
  733.     FILE *f1, *f2;
  734.     string s, n;
  735.     int v, d;
  736.     char m[MAXSTRING];
  737.  
  738.     if (!sam.l)
  739.         return;
  740.     if ((f1 = fopen( Def_Map_filename, "rt")) == NULL) {
  741.         _NOFIL[2] = Def_Map_filename;
  742.         InfoBox(_NOFIL);
  743.         return;
  744.     }
  745.     f2 = fopen("temp.tmp", "wt");
  746.     n = SimplifyName(sam.n);
  747.     v = 1;
  748.     while (v > 0 && (s = GetLine(f1)) != NULL) {
  749.         sscanf(s, "%s %d", m, &d);
  750.         if ((v = strcmp(n, m)) <= 0) {
  751.             fprintf(f2, "%s %d %d %d %d %d %d %d\n", n, sam.m, sam.t[0], sam.t[1],
  752.                 sam.t[2], sam.a[0], sam.a[1], sam.a[2]);
  753.             free(n);
  754.             n = NULL;
  755.             if (v)
  756.                 fprintf(f2, "%s\n", s);
  757.         } else
  758.             fprintf(f2, "%s\n", s);
  759.         free(s);
  760.     }
  761.     while ((s = GetLine(f1))!=NULL) {
  762.         fprintf(f2, "%s\n", s);
  763.         free(s);
  764.     }
  765.     if (n != NULL) {
  766.         fprintf(f2, "%s %d %d %d %d %d %d %d\n", n, sam.m, sam.t[0], sam.t[1],
  767.             sam.t[2], sam.a[0], sam.a[1], sam.a[2]);
  768.         free(n);
  769.     }
  770.     fclose(f2);
  771.     fclose(f1);
  772.     if (unlink( Def_Map_filename )<0 || rename("temp.tmp", Def_Map_filename)<0)
  773.         InfoBox(_NOSAV);
  774. }
  775.  
  776. void SaveSamples(samps s)
  777. /* Post: The desired sample attributes of s have been saved to disk */
  778. {
  779.     int i;
  780.  
  781.     do
  782.         if ((i = Sample(s, NullVal, 0))>=0)
  783.             SaveSamp(s->s[i]);
  784.     while (i>=0);
  785. }
  786.  
  787. void Transpositions(samps s)
  788. /* Post: All necessary transpositions have been applied to the samples s */
  789. {
  790.     int i;
  791.  
  792.     do {
  793.         if ((i = Sample(s, TransVal, 16))>=0) {
  794.             char s1[41];
  795.             string s2;
  796.             samp *sam;
  797.  
  798.             sam = s->s + i;
  799.             if (!sam->t[1])
  800.                 sprintf(s1, "%d", sam->t[0]);
  801.             else if (!sam->t[2])
  802.                 sprintf(s1, "%d,%d", sam->t[0], sam->t[1]);
  803.             else
  804.                 sprintf(s1, "%d,%d,%d", sam->t[0], sam->t[1], sam->t[2]);
  805.             s2 = DialogBox(_TRAQ, s1);
  806.             sam->t[1] = 0;
  807.             sam->t[2] = 0;
  808.             sscanf(s2, "%d,%d,%d", &sam->t[0], &sam->t[1], &sam->t[2]);
  809.             free(s2);
  810.             if ((sam->t[0] || sam->t[1]) && sam->m > 127)
  811.                 InfoBox(_TRANWRN);
  812.             if (sam->t[0]<-128 || sam->t[0]>127 || sam->t[1]<-128 ||
  813.              sam->t[1]>127 || sam->t[2]<-128 || sam->t[2]>127) {
  814.                 InfoBox(_TRANE);
  815.                 sam->t[0] = 0;
  816.                 sam->t[1] = 0;
  817.                 sam->t[2] = 0;
  818.             }
  819.         }
  820.     } while (i>=0);
  821. }
  822.  
  823. void VolumeShifts(samps s)
  824. /* Post: All volume shifting formulae have been defined for the samples s */
  825. {
  826.     int i;
  827.  
  828.     do
  829.         if ((i = Sample(s, VolumeVal, 16))>=0) {
  830.             char s1[41];
  831.             string s2;
  832.             samp *sam;
  833.  
  834.             sam = s->s + i;
  835.             sprintf(s1, "%d,%d,%d", sam->a[0], sam->a[1], sam->a[2]);
  836.             s2 = DialogBox(_VSHQ, s1);
  837.             if (sscanf(s2, "%d,%d,%d", &sam->a[0], &sam->a[1], &sam->a[2])!=3 ||
  838.              sam->a[0] > 127 || sam->a[0] < -128 || sam->a[1] > 127 ||
  839.              sam->a[1] < 0 || sam->a[2] > 127 || sam->a[2] < 1) {
  840.                 InfoBox(_VSHE);
  841.                 sam->a[0] = 0;
  842.                 sam->a[1] = 1;
  843.                 sam->a[2] = 1;
  844.             }
  845.             free(s2);
  846.         }
  847.     while (i>=0);
  848. }
  849.  
  850. void SetDrumChannel( void )
  851. /* Post: Drum channel is set to desired value - 1 */
  852. {
  853.     string s;
  854.     char s2[3];
  855.  
  856.     sprintf(s2, "%d", DrumChann+1);
  857.     s = DialogBox(_DCQ, s2);
  858.     if (sscanf(s, "%d", &DrumChann))
  859.         DrumChann--;        /* Drum channel is stored as value - 1 */
  860. }
  861.  
  862. void SetTempoType( void )
  863. /* Post: Tempo interpretting will either be extended or normal */
  864. {
  865.     char inp;
  866.  
  867.     while ((inp = InfoBoxOld(TempoType ? _TTQ1 : _TTQ0)) != '0' && inp != '1');
  868.     TempoType = inp - '0';
  869. }
  870.  
  871. unsigned char NoteValue(unsigned int n)
  872. /* Returns: MIDI note equivalent of MOD period-lengths */
  873. {
  874.     static unsigned int t[72] = {
  875.         1712, 1616, 1525, 1440, 1357, 1281, 1209, 1141, 1077, 1017, 961, 907,
  876.         856, 808, 762, 720, 678, 640, 604, 570, 538, 508, 480, 453,
  877.         428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226,
  878.         214, 202, 190, 180, 170, 160, 151, 143, 135, 127, 120, 113,
  879.         107, 101, 95, 90, 85, 80, 76, 71, 67, 64, 60, 57,
  880.         53, 50, 48, 45, 42, 40, 38, 36, 34, 32, 30, 28
  881.         };
  882.     signed char a = 0, m = 35, b = 71;
  883.  
  884.     if (!n)
  885.         return 0;
  886.     for (; b-a > 1; m = (a + b) / 2) /* binary search */
  887.         if (t[m] < n)
  888.             b = m;
  889.         else
  890.             a = m;
  891.     if (n - t[b] < t[a] - n) /* choose closest value */
  892.         return (unsigned char)(b + 36);
  893.     return (unsigned char)(a + 36);
  894. }
  895.  
  896. unsigned long NoteLength(unsigned char n, unsigned int l, unsigned int b)
  897. /* Returns: # of ticks to play note length l at pitch n, b beats/min */
  898. {
  899.     unsigned long  idx;
  900.  
  901.     static float t[84] = {
  902.         3.200e-3, 3.020e-3, 2.851e-3, 2.691e-3, 2.540e-3, 2.397e-3,
  903.         2.263e-3, 2.136e-3, 2.016e-3, 1.903e-3, 1.796e-3, 1.695e-3,
  904.         1.600e-3, 1.510e-3, 1.425e-3, 1.345e-3, 1.270e-3, 1.197e-3,
  905.         1.131e-3, 1.068e-3, 1.008e-3, 9.514e-4, 8.980e-4, 8.476e-4,
  906.         8.000e-4, 7.551e-4, 7.127e-4, 6.727e-4, 6.350e-4, 5.993e-4,
  907.         5.657e-4, 5.339e-4, 5.040e-4, 4.757e-4, 4.490e-4, 4.238e-4,
  908.         4.000e-4, 3.775e-4, 3.564e-4, 3.364e-4, 3.175e-4, 2.997e-4,
  909.         2.828e-4, 2.670e-4, 2.520e-4, 2.378e-4, 2.245e-4, 2.119e-4,
  910.         2.000e-4, 1.888e-4, 1.782e-4, 1.682e-4, 1.587e-4, 1.498e-4,
  911.         1.414e-4, 1.335e-4, 1.260e-4, 1.189e-4, 1.122e-4, 1.059e-4,
  912.         1.000e-4, 9.439e-5, 8.909e-5, 8.409e-5, 7.937e-5, 7.492e-5,
  913.         7.071e-5, 6.674e-5, 6.300e-5, 5.946e-5, 5.612e-5, 5.297e-5,
  914.         5.000e-5, 4.719e-5, 4.454e-5, 4.204e-5, 3.969e-5, 3.746e-5,
  915.         3.536e-5, 3.337e-5, 3.150e-5, 2.973e-5, 2.806e-5, 2.649e-5
  916.         }; /* multipliers for each pitch: 12th roots of 2 apart */
  917.  
  918.     idx = (n - 36);
  919.     if( idx < 0 ) idx = 0;
  920.     if( idx > 84 ) idx = 84;
  921.  
  922.     return ( idx * b * l); /* better not slide out of this range :( */
  923. }
  924.  
  925. void WriteHeader(bfile mf, unsigned char n)
  926. /* Post: The MIDI header has been written to mf, with #tracks = n */
  927. {
  928.     static unsigned char MIDIH[14] = {
  929.         77, 84, 104, 100, 0, 0, 0, 6, 0, 1, 0, 255, 0, 192
  930.     };        //MThd
  931.  
  932.     int i = 0;
  933.  
  934.     MIDIH[11] = n+1;
  935.     while (i < 14)
  936.         OutByte(mf, MIDIH[i++]);
  937. }
  938.  
  939. unsigned int Trk0Info(bfile mf, string s)
  940. /*
  941.  * Returns: the number of bytes written as track 0 so far, given mf as the
  942.  *    output MIDI file. s is the name of the tune.
  943.  */
  944. {
  945.     unsigned char name[]= {"*File Copyright (c) 1994 ProJeCT23 SoftWare"};
  946.  
  947.     static unsigned char TRK0I[63] = {
  948.         0, 255, 2, 42, 70, 105, 108, 101, 32, 67, 111, 112, 121, 114, 105, 103,
  949.         104, 116, 32, 40, 99, 41, 32, 49 ,57, 57, 51, 32, 65, 100, 114, 101, 110,
  950.         97, 108, 105, 110, 32, 83, 111, 102, 116, 119, 97, 114, 101,
  951.         0, 255, 88, 4, 3, 2, 24, 8,
  952.         0, 255, 89, 2, 0, 0,
  953.         0, 255, 3
  954.         }; /* standard header + copyright message */
  955.     unsigned int i = 0;
  956.  
  957.     strncpy( &TRK0I[3], name, strlen( name ) );
  958.  
  959.     while (i < 63)
  960.         OutByte(mf, TRK0I[i++]);
  961.     i = 64 + strlen(s);
  962.     OutByte(mf, strlen(s));
  963.     while (*s)
  964.         OutByte(mf, *(s++));
  965.     return i;
  966. }
  967.  
  968. void AddToLog(unsigned long a, unsigned long b)
  969. /* Post: a (file position) and b (number) have been added to the log */
  970. {
  971.     PosLog[PosI++] = b;
  972.     PosLog[PosI++] = a;
  973. }
  974.  
  975. void WriteLog(FILE *f)
  976. /* Post: PosLog has been written into file f */
  977. {
  978.     unsigned long x, y;
  979.     unsigned char c[4];
  980.  
  981.     if (!PosI)
  982.         return;
  983.     x = ftell(f);
  984.     while (PosI) {
  985.         fseek(f, PosLog[--PosI], SEEK_SET);
  986.         y = PosLog[--PosI];
  987.         c[3] = y & 255;
  988.         y >>= 8;
  989.         c[2] = y & 255;
  990.         y >>= 8;
  991.         c[1] = y & 255;
  992.         y >>= 8;
  993.         c[0] = y;
  994.         fwrite(c, 1, 4, f);
  995.     }
  996.     fseek(f, x, SEEK_SET);
  997. }
  998.  
  999. unsigned char RestrictVol(int v)
  1000. /* Returns: A volume in the range 0..127 */
  1001. {
  1002.     if (v < 0)
  1003.         return 0;
  1004.     else
  1005.         return (unsigned char)( (v > 127) ? 127 : v );
  1006. }
  1007.  
  1008.  
  1009.  
  1010.  
  1011.  
  1012. void ConvertMOD(bfile f1, bfile f2, string tn, samps smp)
  1013. /*
  1014.  * Post: The Amiga MODfile f1 has been converted and written to MIDI file f2,
  1015.  *    using instrument mappings smp. Tune has a name tn.
  1016.  */
  1017. {
  1018.     unsigned char b, length, pattern[128];
  1019.     string n, t;
  1020.     unsigned int i, j, k, tempdone = 0;
  1021.     samp *sam;
  1022.     struct bpos p1, p2;
  1023.  
  1024.  
  1025.     p1 = FPos(f1);
  1026.     length = InByte(f1);
  1027.     InByte(f1);
  1028.     for (i = 0; i < 128; pattern[i++] = InByte(f1));
  1029.     Inskipp(f1, (smp->n > 15) ? 4 : 0);
  1030. //    WriteHeader(f2, smp->n);
  1031.     WriteHeader(f2, numoftracks );                // RAUL addition
  1032.     p2 = FPos(f1);
  1033.     for (i = 0, sam = smp->s - 1; i <= smp->n; sam++, i++) {
  1034.         unsigned long cnt, inst, timer, delay[4];
  1035.         unsigned char c;
  1036.  
  1037.         //====== RAUL addition, if sample has length then convert that sample
  1038.         if( sam->l || !i ) {
  1039.             OutByte(f2, 77);        // "MKtr"
  1040.             OutByte(f2, 84);
  1041.             OutByte(f2, 114);
  1042.             OutByte(f2, 107);
  1043.             inst = Beatle(f2); /* store this position so can set AFTERWARDS - hehe */
  1044.             OutByte(f2, 0);
  1045.             OutByte(f2, 0);
  1046.             OutByte(f2, 0);
  1047.             OutByte(f2, 0);
  1048.             if( !i )
  1049.                 cnt = Trk0Info(f2, tn);
  1050.             else {
  1051.                 OutByte(f2, 0);
  1052.                 OutByte(f2, 255);
  1053.                 OutByte(f2, 3);
  1054.                 b = strlen(n = sam->n);
  1055.                 OutByte(f2, b);
  1056.                 cnt = 7 + b;
  1057.                 while (b--)
  1058.                     OutByte(f2, *(n++));
  1059.                 c = sam->c;
  1060.                 OutByte(f2, 0);
  1061.                 OutByte(f2, 0xC0 + c); /* set channel */
  1062.                 OutByte(f2, (sam->m > 127) ? 126 : (sam->m));
  1063.             }
  1064.         }
  1065.  
  1066.         timer = 0;
  1067.         if (sam->l || !i) {
  1068.             unsigned int bpm, ticks, l, effect, h;
  1069.             unsigned char sampnum, lastsam[4] = {0}, vol[4];
  1070.             signed char patbreak;
  1071.             unsigned long x, pause;
  1072.             int note, lastslide, slideto;
  1073.             int n[4][48][2]; /* note data for a song position */
  1074.             int lastn[4]; /* last note on a particular channel */
  1075.  
  1076.             sprintf(_CNVPOS[2]+7, "%d", i); /* some compilers hate this */
  1077.             DrawBox(_CNVPOS);
  1078.             memset(lastn, 0, 4 * sizeof(int));
  1079.             memset(vol, 0, 4);
  1080.             memset(delay, 0, 4 * sizeof(long));
  1081.             bpm = 125;
  1082.             ticks = 6;
  1083.             lastslide = slideto = 0;
  1084.             patbreak = 0;
  1085.             for (h = 48; h--; )
  1086.                 for (k = 4; k--; )
  1087.                     n[k][h][0] = 0;
  1088.             for (l = 0; l < length; l++) {
  1089.                 if (pattern[l]<=pattern[l-1] || !l) {
  1090.                     FGoto(f1, p2);
  1091.                     x = (unsigned) 1024 * pattern[l];
  1092.                 } else
  1093.                     x = (unsigned) 1024 * (pattern[l]-pattern[l-1]-1);
  1094.                 Inskipp(f1, x);
  1095.                 j = 64;
  1096.                 if (patbreak>0)
  1097.                     patbreak = 1-patbreak;
  1098.                 while (j--) {
  1099.                     pause = 0;
  1100.                     if (patbreak)
  1101.                         Inskipp(f1, 16);
  1102.                     else
  1103.                         for (k = 0; k < 4; k++) {
  1104.                             n[k][0][1] = sam->v;
  1105.                             sampnum = InByte(f1);
  1106.                             note = ((sampnum & 15) << 8) + InByte(f1);
  1107.                             effect = InByte(f1);
  1108.                             sampnum = (sampnum & ~15) + (effect >> 4);
  1109.                             if (!i)
  1110.                                 note = 0;
  1111.                             if ((note || sampnum) && delay[k]) { /* stop old note */
  1112.                                 cnt += 3 + WriteVLQ(f2, timer);
  1113.                                 timer = 0;
  1114.                                 OutByte(f2, 0x80 + c); /* note off */
  1115.                                 OutByte(f2, ENOTE(lastn[k], 0));
  1116.                                 OutByte(f2, RestrictVol(EVOL(vol[k])));
  1117.                                 if (sam->t[1]) {
  1118.                                     cnt += 4;
  1119.                                     OutByte(f2, 0);
  1120.                                     OutByte(f2, 0x80 + c);
  1121.                                     OutByte(f2, ENOTE(lastn[k], 1));
  1122.                                     OutByte(f2, RestrictVol(EVOL(vol[k])));
  1123.                                     if (sam->t[2]) {
  1124.                                         cnt += 4;
  1125.                                         OutByte(f2, 0);
  1126.                                         OutByte(f2, 0x80 + c);
  1127.                                         OutByte(f2, ENOTE(lastn[k], 2));
  1128.                                         OutByte(f2, RestrictVol(EVOL(vol[k])));
  1129.                                     }
  1130.                                 }
  1131.                                 delay[k] = 0;
  1132.                             }
  1133.                             if (!note && sampnum == i) /* check "defaults" */
  1134.                                 note = lastn[k];
  1135.                             else if (!sampnum)
  1136.                                 if (lastsam[k] == i)
  1137.                                     sampnum = i;
  1138.                                 else
  1139.                                     note = 0;
  1140.                             else {
  1141.                                 if (sampnum != i)
  1142.                                     note = 0;
  1143.                                 lastsam[k] = sampnum;
  1144.                             }
  1145.                             n[k][0][0] = note;
  1146.                             effect = ((effect & 15) << 8) + InByte(f1);
  1147.  
  1148.                             switch (effect & 0xF00) {
  1149.                                 case 0x000: { /* arpeggio */
  1150.                                     int nv;
  1151.  
  1152.                                     if (!i || !effect || sam->m > 127)
  1153.                                         break;
  1154.                                     if (!note)
  1155.                                         if (!delay[k])
  1156.                                             break;
  1157.                                         else {
  1158.                                             nv = NoteValue(lastn[k]);
  1159.                                             n[k][47][0] = lastn[k];
  1160.                                             n[k][47][1] = vol[k];
  1161.                                             if (effect & 0x0F0)
  1162.                                                 n[k][16][0] = -(nv + ((effect & 0x0F0) >> 4));
  1163.                                             n[k][16][1] = vol[k];
  1164.                                             if (effect & 0x00F)
  1165.                                                 n[k][32][0] = -(nv + (effect & 0x00F));
  1166.                                             n[k][32][1] = vol[k];
  1167.                                         }
  1168.                                     else {
  1169.                                         nv = NoteValue(note);
  1170.                                         n[k][47][0] = note;
  1171.                                         n[k][47][1] = sam->v;
  1172.                                         if (effect & 0x0F0)
  1173.                                             n[k][16][0] = -(nv + ((effect & 0x0F0) >> 4));
  1174.                                         n[k][16][1] = sam->v;
  1175.                                         if (effect & 0x00F)
  1176.                                             n[k][32][0] = -(nv + (effect & 0x00F));
  1177.                                         n[k][32][1] = sam->v;
  1178.                                     }
  1179.                                     break;
  1180.                                     }
  1181.                                 case 0x300: /* slide to */
  1182.                                     if (!note && !slideto || note==lastn[k] || sam->m > 127)
  1183.                                         break;
  1184.                                     if (effect & 0x0FF)
  1185.                                         lastslide = effect & 0x0FF;
  1186.                                     else
  1187.                                         lastslide = abs(lastslide);
  1188.                                     if (note)
  1189.                                         slideto = note;
  1190.                                     if (slideto > lastn[k]) {
  1191.                                         n[k][0][0] = lastn[k] + lastslide*(ticks-1);
  1192.                                         if (n[k][0][0] > 856)
  1193.                                             n[k][0][0] = 856;
  1194.                                         if (n[k][0][0] > slideto)
  1195.                                             n[k][0][0] = slideto;
  1196.                                     } else {
  1197.                                         n[k][0][0] = lastn[k] - lastslide*(ticks-1);
  1198.                                         if (n[k][0][0] < 113)
  1199.                                             n[k][0][0] = 113;
  1200.                                         if (n[k][0][0] < slideto)
  1201.                                             n[k][0][0] = slideto;
  1202.                                     }
  1203.                                     n[k][0][1] = vol[k];
  1204.                                     break;
  1205.                                 case 0x100: /* slide up */
  1206.                                 case 0x200: /* slide down */
  1207.                                     if (!(effect & 0x0FF) || sam->m > 127)
  1208.                                         break;
  1209.                                     if (effect & 0x200)
  1210.                                         lastslide = effect & 0x0FF;
  1211.                                     else
  1212.                                         lastslide = -(effect & 0x0FF);
  1213.                                     if (!note)
  1214.                                         if (!delay[k])
  1215.                                             break;
  1216.                                         else {
  1217.                                             n[k][0][0] = lastn[k] + lastslide;
  1218.                                             n[k][0][1] = vol[k];
  1219.                                         }
  1220.                                     else
  1221.                                         n[k][0][0] += lastslide;
  1222.                                     if (n[k][0][0] > 856)
  1223.                                         n[k][0][0] = 856;
  1224.                                     else if (n[k][0][0] < 113)
  1225.                                         n[k][0][0] = 113;
  1226.                                     break;
  1227.                                 case 0x400: /* vibrato */
  1228.                                 case 0x700: /* tremolo */
  1229.                                     /* ignore these effects.. not convertable */
  1230.                                     break;
  1231.                                 case 0x500: /* slide to & volume slide */
  1232.                                     if ((note || slideto) && note!=lastn[k] && sam->m < 128) {
  1233.                                         if (note)
  1234.                                             slideto = note;
  1235.                                         if (slideto > lastn[k]) {
  1236.                                             n[k][0][0] = lastn[k] + lastslide*(ticks-1);
  1237.                                             if (n[k][0][0] > 856)
  1238.                                                 n[k][0][0] = 856;
  1239.                                             if (n[k][0][0] > slideto)
  1240.                                                 n[k][0][0] = slideto;
  1241.                                         } else {
  1242.                                             n[k][0][0] = lastn[k] - lastslide*(ticks-1);
  1243.                                             if (n[k][0][0] < 113)
  1244.                                                 n[k][0][0] = 113;
  1245.                                             if (n[k][0][0] < slideto)
  1246.                                                 n[k][0][0] = slideto;
  1247.                                         }
  1248.                                     } else
  1249.                                         n[k][0][0] = 0;
  1250.                                     note = 0;
  1251.                                 case 0x600: /* vibrato & volume slide */
  1252.                                 case 0xA00: { /* volume slide */
  1253.                                     int v;
  1254.  
  1255.                                     if (!note)
  1256.                                         v = vol[k];
  1257.                                     else
  1258.                                         v = sam->v;
  1259.                                     v += (ticks-1)*(effect & 0x0F0); /* can't really slide */
  1260.                                     v -= (ticks-1)*(effect & 0x00F);
  1261.                                     if (v > 127)
  1262.                                         v = 127;
  1263.                                     else if (v < 0)
  1264.                                         v = 0;
  1265.                                     n[k][0][1] = v;
  1266.                                     break;
  1267.                                     }
  1268.                                 case 0x900: /* set offset: pretend it's retrigger */
  1269.                                     if ((!n[k][0][0] || !sampnum) && delay[k]) {
  1270.                                         n[k][0][0] = lastn[k];
  1271.                                         n[k][0][1] = vol[k];
  1272.                                     }
  1273.                                     break;
  1274.                                 case 0xB00: /* position jump: ignore, but break anyway */
  1275.                                     patbreak = 1;
  1276.                                     break;
  1277.                                 case 0xD00: /* pattern break */
  1278.                                     patbreak = 1 + 10 * (effect & 0x0F0) + (effect & 0x00F);
  1279.                                     break;
  1280.                                 case 0xC00: /* set volume */
  1281.                                     {
  1282.                                         int vol = effect;                // CHANGE BY RAUL
  1283.                                         if( vol == 0x40 ) vol=0x3f;
  1284.                                         vol = vol&0x3f;
  1285.                                         n[k][0][1] = vol<<1;
  1286.                                     //    n[k][0][1] = effect&0x7f;
  1287.                                     }
  1288.                                     break;
  1289.                                 case 0xF00: { /* set tempo */
  1290.                                     int temp;
  1291.  
  1292.                                     temp = effect & 0x0FF;
  1293.                                     if (!temp)
  1294.                                         temp = 1;
  1295.                                     if (temp < 32) {
  1296.                                         ticks = temp;
  1297.                                         if (TempoType) {  /* Tempos act strangely so .. */
  1298.                                             bpm = 750 / temp;
  1299.                                             x = 80000 * temp;
  1300.                                         }
  1301.                                     } else {
  1302.                                         bpm = temp;
  1303.                                         x = 60000000 / temp;
  1304.                                     }
  1305.                                     if (i)
  1306.                                         break; /* only write tempo on track 0 */
  1307.                                     cnt += 6 + WriteVLQ(f2, timer);
  1308.                                     timer = 0;
  1309.                                     OutByte(f2, 255); /* meta-event */
  1310.                                     OutByte(f2, 81); /* set tempo */
  1311.                                     OutByte(f2, 3);
  1312.                                     OutByte(f2, x >> 16);
  1313.                                     OutByte(f2, (x >> 8) & 0xFF);
  1314.                                     OutByte(f2, x & 0xFF);
  1315.                                     tempdone = 1;
  1316.                                     break;
  1317.                                     }
  1318.                                 case 0xE00: /* extended effects */
  1319.                                     switch (effect & 0x0F0) {
  1320.                                         case 0x010: /* fine slide up */
  1321.                                             if (!(effect & 0x00F) || sam->m > 127)
  1322.                                                 break;
  1323.                                             if (!note)
  1324.                                                 if (!delay[k])
  1325.                                                     break;
  1326.                                                 else {
  1327.                                                     n[k][h][0] = lastn[k] + (effect & 0x00F);
  1328.                                                     n[k][h][1] = vol[k];
  1329.                                                 }
  1330.                                             else
  1331.                                                 n[k][h][0] += effect & 0x00F;
  1332.                                             break;
  1333.                                         case 0x020: /* fine slide down */
  1334.                                             if (!(effect & 0x00F) || sam->m > 127)
  1335.                                                 break;
  1336.                                             if (!note)
  1337.                                                 if (!delay[k])
  1338.                                                     break;
  1339.                                                 else {
  1340.                                                     n[k][h][0] = lastn[k] - (effect & 0x00F);
  1341.                                                     n[k][h][1] = vol[k];
  1342.                                                 }
  1343.                                             else
  1344.                                                 n[k][h][0] -= effect & 0x00F;
  1345.                                             break;
  1346.                                         case 0x000: /* set filter on/off */
  1347.                                         case 0x030: /* glissando on/off */
  1348.                                         case 0x040: /* set vibrato wave */
  1349.                                         case 0x050: /* set finetune */
  1350.                                         case 0x060: /* pattern loop */
  1351.                                         case 0x070: /* set tremolo wave */
  1352.                                         case 0x080: /* un-used */
  1353.                                         case 0x0F0: /* invert loop */
  1354.                                             /* can't do these in MIDI.. ignore */
  1355.                                             break;
  1356.                                         case 0x0A0: /* fine volume slide up */
  1357.                                         case 0x0B0: { /* fine volume slide down */
  1358.                                             int v;
  1359.  
  1360.                                             v = sam->v;
  1361.                                             if (effect & 0x0A0)
  1362.                                                 v += effect & 0x00F;
  1363.                                             else
  1364.                                                 v -= effect & 0x00F;
  1365.                                             if (v<0)
  1366.                                                 v = 0;
  1367.                                             else if (v>127)
  1368.                                                 v = 127;
  1369.                                             n[k][0][1] = v;
  1370.                                             break;
  1371.                                             }
  1372.                                         case 0x090: { /* retrigger sample */
  1373.                                             int a, b, c;
  1374.  
  1375.                                             if (!note && !delay[k] || !(effect & 0x00F))
  1376.                                                 break;
  1377.                                             a = effect & 0x00F;
  1378.                                             if (!(ticks / a))
  1379.                                                 break;
  1380.                                             if (!note) {
  1381.                                                 n[k][0][0] = lastn[k];
  1382.                                                 n[k][0][1] = vol[k];
  1383.                                             }
  1384.                                             c = 0;
  1385.                                             b = 1;
  1386.                                             a *= 48;
  1387.                                             while (c < 48) {
  1388.                                                 n[k][c][0] = note;
  1389.                                                 n[k][c][1] = n[k][0][1];
  1390.                                                 c = b * a / ticks;
  1391.                                                 b++;
  1392.                                             }
  1393.                                             break;
  1394.                                             }
  1395.                                         case 0x0C0: { /* cut sample */
  1396.                                             int a;
  1397.  
  1398.                                             if (!note && !delay[k])
  1399.                                                 break;
  1400.                                             a = 48 * (effect & 0x00F) / ticks;
  1401.                                             if (a > 47)
  1402.                                                 break;
  1403.                                             if (note)
  1404.                                                 n[k][a][0] = note;
  1405.                                             else
  1406.                                                 n[k][a][0] = lastn[k];
  1407.                                             n[k][a][1] = 0;
  1408.                                             break;
  1409.                                             }
  1410.                                         case 0x0D0: { /* delay sample */
  1411.                                             int a;
  1412.  
  1413.                                             if (!note || !(effect & 0x00F))
  1414.                                                 break;
  1415.                                             a = 48 * (effect & 0x00F) / ticks;
  1416.                                             n[k][0][0] = 0;
  1417.                                             if (a > 47)
  1418.                                                 break;
  1419.                                             n[k][a][0] = note;
  1420.                                             n[k][a][1] = n[k][a][0];
  1421.                                             break;
  1422.                                             }
  1423.                                         case 0x0E0: /* pattern pause */
  1424.                                             pause = 48 * (effect & 0x00F);
  1425.                                             break;
  1426.                                     }
  1427.                                     break;
  1428.                                 /* else dunno what it does.. disbelieve it ;) */
  1429.                             }
  1430.                         }
  1431.                     for (h = 0; h<48; h++) {
  1432.                         for (k = 0; k < 4; k++)
  1433.                             if (n[k][h][0]) {
  1434.                                 if (delay[k]) { /* turn off old note on same channel */
  1435.                                     cnt += 3 + WriteVLQ(f2, timer);
  1436.                                     timer = 0;
  1437.                                     OutByte(f2, 0x80 + c); /* note off */
  1438.                                     OutByte(f2, ENOTE(lastn[k], 0));
  1439.                                     OutByte(f2, RestrictVol(EVOL(vol[k])));
  1440.                                     if (sam->t[1]) {
  1441.                                         cnt += 4;
  1442.                                         OutByte(f2, 0);
  1443.                                         OutByte(f2, 0x80 + c);
  1444.                                         OutByte(f2, ENOTE(lastn[k], 1));
  1445.                                         OutByte(f2, RestrictVol(EVOL(vol[k])));
  1446.                                         if (sam->t[2]) {
  1447.                                             cnt += 4;
  1448.                                             OutByte(f2, 0);
  1449.                                             OutByte(f2, 0x80 + c);
  1450.                                             OutByte(f2, ENOTE(lastn[k], 2));
  1451.                                             OutByte(f2, RestrictVol(EVOL(vol[k])));
  1452.                                         }
  1453.                                     }
  1454.                                     delay[k] = 0;
  1455.                                 }
  1456.                                 lastn[k] = n[k][h][0];
  1457.                                 n[k][h][0] = 0;
  1458.                                 vol[k] = n[k][h][1];
  1459.                                 cnt += 3 + WriteVLQ(f2, timer);
  1460.                                 timer = 0;
  1461.                                 OutByte(f2, 0x90 + c); /* note on */
  1462.                                 OutByte(f2, ENOTE(lastn[k], 0));
  1463.                                 OutByte(f2, RestrictVol(EVOL(vol[k])));
  1464.                                 if (sam->t[1]) {
  1465.                                     cnt += 4;
  1466.                                     OutByte(f2, 0);
  1467.                                     OutByte(f2, 0x90 + c);
  1468.                                     OutByte(f2, ENOTE(lastn[k], 1));
  1469.                                     OutByte(f2, RestrictVol(EVOL(vol[k])));
  1470.                                     if (sam->t[2]) {
  1471.                                         cnt += 4;
  1472.                                         OutByte(f2, 0);
  1473.                                         OutByte(f2, 0x90 + c);
  1474.                                         OutByte(f2, ENOTE(lastn[k], 2));
  1475.                                         OutByte(f2, RestrictVol(EVOL(vol[k])));
  1476.                                     }
  1477.                                 }
  1478.                                 delay[k] = NoteLength(ANOTE(lastn[k]), sam->l, bpm);
  1479.                             } else if (delay[k]==1) {
  1480.                                 delay[k] = 0;
  1481.                                 cnt += 3 + WriteVLQ(f2, timer);
  1482.                                 timer = 0;
  1483.                                 OutByte(f2, 0x80 + c); /* note off */
  1484.                                 OutByte(f2, ENOTE(lastn[k], 0));
  1485.                                 OutByte(f2, RestrictVol(EVOL(vol[k])));
  1486.                                 if (sam->t[1]) {
  1487.                                     cnt += 4;
  1488.                                     OutByte(f2, 0);
  1489.                                     OutByte(f2, 0x80 + c);
  1490.                                     OutByte(f2, ENOTE(lastn[k], 1));
  1491.                                     OutByte(f2, RestrictVol(EVOL(vol[k])));
  1492.                                     if (sam->t[2]) {
  1493.                                         cnt += 4;
  1494.                                         OutByte(f2, 0);
  1495.                                         OutByte(f2, 0x80 + c);
  1496.                                         OutByte(f2, ENOTE(lastn[k], 2));
  1497.                                         OutByte(f2, RestrictVol(EVOL(vol[k])));
  1498.                                     }
  1499.                                 }
  1500.                             } else if (delay[k]>0)
  1501.                                 delay[k]--;
  1502.                         timer++;
  1503.                     }
  1504.                     timer += pause;
  1505.                     if (patbreak<0)
  1506.                         patbreak++;
  1507.                     else if (patbreak>0) {
  1508.                         patbreak = 1 - patbreak;
  1509.                         while (j) {
  1510.                             j--;
  1511.                             Inskipp(f1, 16); /* 16 bytes / song position */
  1512.                         }
  1513.                     }
  1514.                 }
  1515.             }
  1516.             for (k = 0; k < 4; k++)
  1517.                 if (delay[k]) {
  1518.                     cnt += 3 + WriteVLQ(f2, timer);
  1519.                     timer = 0;
  1520.                     OutByte(f2, 0x80 + c); /* note off */
  1521.                     OutByte(f2, ENOTE(lastn[k], 0));
  1522.                     OutByte(f2, RestrictVol(EVOL(vol[k])));
  1523.                     if (sam->t[1]) {
  1524.                         cnt += 4;
  1525.                         OutByte(f2, 0);
  1526.                         OutByte(f2, 0x80 + c);
  1527.                         OutByte(f2, ENOTE(lastn[k], 1));
  1528.                         OutByte(f2, RestrictVol(EVOL(vol[k])));
  1529.                         if (sam->t[2]) {
  1530.                             cnt += 4;
  1531.                             OutByte(f2, 0);
  1532.                             OutByte(f2, 0x80 + c);
  1533.                             OutByte(f2, ENOTE(lastn[k], 2));
  1534.                             OutByte(f2, RestrictVol(EVOL(vol[k])));
  1535.                         }
  1536.                     }
  1537.                 }
  1538.         }
  1539.         if(!i && !tempdone) {
  1540.             cnt += 7;
  1541.             OutByte(f2, 0); /* give the default 128 bpm if none done yet */
  1542.             OutByte(f2, 255);
  1543.             OutByte(f2, 81);
  1544.             OutByte(f2, 3);
  1545.             OutByte(f2, 7);
  1546.             OutByte(f2, 39);
  1547.             OutByte(f2, 14);
  1548.         }
  1549.         if( sam->l || !i ) {                                // RAUL addition
  1550.             cnt += 3 + WriteVLQ(f2, timer);
  1551.             OutByte(f2, 255);
  1552.             OutByte(f2, 47);
  1553.             OutByte(f2, 0);
  1554.             AddToLog(inst, cnt); /* process this later */
  1555.             FGoto(f1, p2);
  1556.         }
  1557.     }
  1558.     ClearWin();
  1559.     FlushOut(f2);
  1560.     WriteLog(f2->f);
  1561.     FGoto(f1, p1);
  1562. }
  1563.  
  1564. int main(int argc, char *argv[])
  1565. {
  1566.     int c;
  1567.  
  1568.     printf("Mod2midi converter © 1994 Feb, by Raul Sobon\n");
  1569.  
  1570.     MainWindow("MOD2MIDI 1.2 - Amiga Sound/Protracker to MIDI converter",
  1571.         4, "File", 'f', "Samples", 's', "Options", 'o', "Help", 'h');
  1572.  
  1573. /*    SetMenu(0, 6, "Dest. midi",'d',0, "Source mod",'s',1, "------------",-1,-1,
  1574.         "Convert",'c',2, "------------",-1,-1, "Quit",'q',99);
  1575.     SetMenu(1, 5, "Map samples",'m',3, "Transposing",'t',6, "Volume shift",'v',9,
  1576.         "------------",-1,-1, "Save info",'s',4);
  1577.     SetMenu(2, 2, "Drum channel",'d',7, "Tempo type",'t',8);
  1578.     SetMenu(3, 1, "About",'a',5);
  1579. */
  1580.     MidFile->f = ModFile->f = NULL;
  1581.     MidFN = ModFN = NULL;
  1582.     if (argc>2) {
  1583.         strcpy(MidFN = (string) malloc(strlen(argv[2])+1), argv[2]);
  1584.         if (fclose(fopen(MidFN, "r"))==EOF || InfoBoxOld(_OUTE)=='y')
  1585.             OpenOut(MidFile, MidFN);
  1586.         if (MidFile->f==NULL) {
  1587.             free(MidFN);
  1588.             MidFN = NULL;
  1589.         }
  1590.     }
  1591.     if (argc>1) {
  1592.         strcpy(ModFN = (string) malloc(strlen(argv[1])+1), argv[1]);
  1593.         if (OpenIn(ModFile, ModFN))
  1594.             if (!ReadModSpecs(ModFile, SongName, Samples))
  1595.                 InfoBox(_MODE);
  1596.             else if (!SetDefaults(Samples, ModFN))
  1597.                 CloseIn(ModFile);
  1598.         if (ModFile->f==NULL) {
  1599.             free(ModFN);
  1600.             ModFN = NULL;
  1601.         }
  1602.     }
  1603.  
  1604. //    c = Choice();
  1605.  
  1606.     InfoBox(_ABOUT);
  1607.  
  1608.     do {
  1609.         c = Choice();
  1610.         switch(c) {
  1611.             case 0:
  1612.                 MidFN = InitFile(MidFile, MidFN, "MIDI file below.", 0);
  1613.                 break;
  1614.             case 1:
  1615.                 if (ModFile->f != NULL)
  1616.                     SaveDefaults(Samples, ModFN); /* make sure defaults are saved */
  1617.                 ModFN = InitFile(ModFile, ModFN, "MOD file below.", 1);
  1618.                 if (ModFN != NULL) {
  1619.                     if (!ReadModSpecs(ModFile, SongName, Samples)){
  1620.                         InfoBox(_MODE);
  1621.                     }
  1622.                     else
  1623.                     if (!SetDefaults(Samples, ModFN)) {
  1624.                         CloseIn(ModFile);
  1625.                     }
  1626.                 }
  1627.                 break;
  1628.             case 2:
  1629.                 if (MidFile->f != NULL && ModFile->f != NULL)
  1630.                     if ( (numoftracks=ChooseChannels(Samples)) <= 16)
  1631.                         ConvertMOD(ModFile, MidFile, SongName, Samples);
  1632.                     else
  1633.                         InfoBox(_TMC);
  1634.                 else
  1635.                     InfoBox(_CNVE);
  1636.                 break;
  1637.             case 3:
  1638.                 if (ModFile->f != NULL)
  1639.                     MapSamples(Samples);
  1640.                 else
  1641.                     InfoBox(_MODM);
  1642.                 break;
  1643.             case 4:
  1644.                 if (ModFile->f != NULL)
  1645.                     SaveSamples(Samples);
  1646.                 else
  1647.                     InfoBox(_MODM);
  1648.                 break;
  1649.             case 5:
  1650.                 InfoBox(_ABOUT);
  1651.                 break;
  1652.             case 6:
  1653.                 if (ModFile->f != NULL)
  1654.                     Transpositions(Samples);
  1655.                 else
  1656.                     InfoBox(_MODM);
  1657.                 break;
  1658.             case 7:
  1659.                 SetDrumChannel();
  1660.                 break;
  1661.             case 8:
  1662.                 SetTempoType();
  1663.                 break;
  1664.             case 9:
  1665.                 if (ModFile->f != NULL)
  1666.                     VolumeShifts(Samples);
  1667.                 else
  1668.                     InfoBox(_MODM);
  1669.                 break;
  1670.         }
  1671.     } while (c != 99);
  1672.     if (ModFile->f != NULL) {
  1673.         CloseIn(ModFile);
  1674.         SaveDefaults(Samples, ModFN);
  1675.     }
  1676.     free(ModFN);
  1677.     if (MidFile->f != NULL)
  1678.         CloseOut(MidFile);
  1679.     free(MidFN);
  1680.     EndWindows();
  1681.     exit(0);
  1682. }
  1683.  
  1684.